/* Name: main.c
 * Author: <insert your name here>
 * Copyright: <insert your copyright message here>
 * License: <insert your license reference here>
 */
#include "uart.h"
#include "usbdrv.h"
#include "oddebug.h"
#include "hardware.h"
#include "serial.h"
#include "ds18b20.h"
#include "ircode.h"
#include "command.h"
#include "cbuf.h"
#include "gpio.h"

#include <stdio.h>
#include <string.h>
#include <util/delay.h>

#if (ENA_USB && ENA_PLC)
# error Not enough resource to enable PLC and USB functions at the same time
#endif

uint8_t Temperature[2] = {0, 0};
static uint32_t SystemTick = 0;

#if (ENA_USB)
static int usbRead(char *buffer, int len);
static int usbWrite(const char *buffer, int len);

// buffer for host-pc write, device-self to read
CBUF_ALLOC(usbHWDR, USB_HWDR_SIZEB);
// buffer for host-pc read, device-self to write
CBUF_ALLOC(usbHRDW, USB_HRDW_SIZEB);

static proc_package_t usbCmdNode = {usbRead, usbWrite, 0};
static proc_package_t uartCmdNode = {uartRead, uartWrite, 0};
#endif

#if (ENA_PLC)
static int plcRead(char *buffer, int len);
static int plcWrite(const char *buffer, int len);

CBUF_ALLOC(plcHWDR, PLC_HWDR_SIZEB);
CBUF_ALLOC(plcHRDW, PLC_HRDW_SIZEB);

static proc_package_t plcCmdNode = {plcRead, plcWrite, 0};
#endif
	
int main(void)	{
#if (ENA_USB)
	uchar i = 0;
#endif
	char serialNumber[6];
	
	uart1_open(115200);

	io_output_low(LED_PORT, LED_PIN);
	io_output_low(BLRST_PORT, BLRST_PIN);
	
	// timer2 as temperature period read
	TCCR2 = (7 << 0);
	TIMSK = (1 << 6);
	
	readSerialNumber(serialNumber);
	
#if (ENA_PLC)
	sei();
	wdt_enable(WDTO_2S);
	while (1)
	{
		wdt_reset();
		processCommandStream(&plcCmdNode);
	}
#elif (ENA_USB)
	odDebugInit();
    DBG1(0x00, 0, 0);       /* debug output: main starts */
    usbInit();
    usbDeviceDisconnect();  /* enforce re-enumeration, do this while interrupts are disabled! */
	
	wdt_enable(WDTO_2S);
	
	i = 0;
    while(-- i) {            /* fake USB disconnect for > 250 ms */
        wdt_reset();
        _delay_ms(1);
    }
	
    usbDeviceConnect();
    sei();
    DBG1(0x01, 0, 0);       /* debug output: main loop starts */
	
    for(;;){                /* main event loop */
        DBG1(0x02, 0, 0);   /* debug output: main loop iterates */
        wdt_reset();
        usbPoll();
		processCommandStream(&usbCmdNode);
		processCommandStream(&uartCmdNode);
    }
#endif
    return 0;
}

#if (ENA_USB)
usbMsgLen_t usbFunctionSetup(uchar data[8])	{
	// usbRequest_t *rq = (void *)data;
	// if((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_VENDOR);
	return USB_NO_MSG;
}

#if (USB_CFG_IMPLEMENT_FN_READ)
uchar usbFunctionRead(uchar *data, uchar len) {
	return CBufRead(&usbHRDW, (char *)data, len);
}
#endif

/* ------------------------------------------------------------------------- */
#if (USB_CFG_IMPLEMENT_FN_WRITE)
uchar   usbFunctionWrite(uchar *data, uchar len) {
	return CBufWrite(&usbHWDR, (const char *)data, len);
}
#endif

static int usbRead(char *buffer, int len) {
	return CBufRead(&usbHWDR, buffer, len);
}

static int usbWrite(const char *buffer, int len) {
	return CBufWrite(&usbHRDW, buffer, len);
}
#endif // #if (ENA_USB)

#if (ENA_PLC)
static int plcRead(char *buffer, int len) {
	return CBufRead(&plcHWDR, buffer, len);
}

static int plcWrite(const char *buffer, int len) {
	return CBufWrite(&plcHRDW, buffer, len);
}
#endif


uint32_t getTickCount16_7ms() {
	return SystemTick;
}
	

// every 16.7ms
ISR(TIMER2_OVF_vect) {
	static int count = 0;
	char buffer[2];
	
	count ++;
	SystemTick ++;
	
	// every 5s
	if (count >= 300)
	{
		count = 0;
		// DBG("temp!");
		if (readTemp(buffer) == 0)
		{
			Temperature[1] = buffer[0];
			Temperature[0] = buffer[1];
		}
	}
}




